package com.gitee.cnlongdb.server.connect.nettymission.handler;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

/**
 * 系统名称：NettyServerHandler.java
 * 模块名称：
 * 模块描述：netty-消息处理执行类
 * 功能列表：
 * 模块作者：ZOUYONG
 * 开发时间：2019年4月10日 下午10:26:13
 * 模块路径：com.gitee.cnlongdb.server.connect.nettymission.handler.NettyServerHandler
 * 更新记录：
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

	private final Logger logger = (Logger) LoggerFactory.getLogger(NettyServerHandler.class);

	// 执行对象
	private Object object;
	private String methodName = "getNettyClientMessage";
	private Class[] paramsClass = { String.class };

	public NettyServerHandler(Object object) {
		this.object = object;
	}

	/**
	 * channelAction channel 通道 action 活跃的
	 * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
	 */
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		// System.out.println(ctx.channel().localAddress().toString() + " 通道已激活！");
	}

	/**
	 * channelInactive channel 通道 Inactive 不活跃的
	 * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
	 */
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		// System.out.println(ctx.channel().localAddress().toString() + " 通道不活跃，或许连接已关闭！");
	}

	/**
	 * 功能：读取客户端发送过来的信息
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		ByteBuf buf = (ByteBuf) msg;
		String message = getMessage(buf);
		if (StringUtils.isNotBlank(message)) {
			Object result = "fail";
			try {
				result = object.getClass().getMethod(methodName, paramsClass).invoke(object, new Object[] { message });
			} catch (Exception e) {
				result = e.getMessage();
				logger.error("处理客户端请求数据异常：{}", result);
			}
			ctx.writeAndFlush(Unpooled.copiedBuffer(result.toString(), CharsetUtil.UTF_8)); // 必须有flush
		}
	}

	/**
	 * 此处用来处理收到的数据中含有中文的时 出现乱码的问题
	 * 
	 * @param buf
	 * @return
	 */
	private String getMessage(ByteBuf buf) {
		byte[] con = new byte[buf.readableBytes()];
		buf.readBytes(con);
		try {
			return new String(con, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 功能：读取完毕客户端发送过来的数据之后的操作 服务端接收数据完毕.
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		// 第一种方法：写一个空的buf，并刷新写出区域。完成后关闭sock channel连接。
		ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
		// ctx.flush();
		// ctx.flush(); //
		// 第二种方法：在client端关闭channel连接，这样的话，会触发两次channelReadComplete方法。
		// ctx.flush().close().sync(); // 第三种：改成这种写法也可以，但是这中写法，没有第一种方法的好。
	}

	/**
	 * 功能：服务端发生异常的操作
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		ctx.close();
		// System.out.println("异常信息：\r\n" + cause.getMessage());
	}

}
